package matrix;

public class GaussElimPiv extends SSLE {

	@Override
	protected void solve(boolean buildSteps) throws Exception {
		Matrix g = a.augment(b);
		if (buildSteps) {
			steps.add("[A|B]");
			steps.add(g.toLatex(new int[] { a.width() }));
		} // fwd elm
		if (buildSteps)
			steps.add("Forward \\;\\; elimination \\;\\; with \\;\\; pivoting");
		for (int i = 0; i < g.height() - 1; i++) {
			int r = g.pivot(i, i);
			g.swapRow(i, r);
			if (buildSteps && i != r) {
				steps.add("R" + (i + 1) + "\\leftrightarrow R" + (r + 1));
				steps.add(g.toLatex(new int[] { a.width() }));
			}
			for (int j = i + 1; j < g.height(); j++)
				g.solveRows(i, j, i);
			if (buildSteps)
				steps.add(g.toLatex(new int[] { a.width() }));
		}
		// bck sub
		if (buildSteps)
			steps.add("Backward \\;\\; substitution");
		for (int i = g.height() - 1; i >= 0; i--) {
			x.set(0, i, g.get(g.width() - 1, i));
			if (buildSteps)
				steps.add("x_" + (i + 1) + "={" + g.get(g.width() - 1, i));
			for (int j = i + 1; j < g.height(); j++) {
				x.set(0, i, x.get(0, i).doubleValue() - x.get(0, j).doubleValue() * g.get(j, i).doubleValue());
				if (buildSteps)
					steps.set(steps.size() - 1, steps.get(steps.size() - 1) + "-" + g.get(j, i).doubleValue() + "*x_" + (j + 1));
			}
			x.set(0, i, x.get(0, i).doubleValue() / g.get(i, i).doubleValue());
			if (buildSteps) {
				steps.set(steps.size() - 1, steps.get(steps.size() - 1) + "\\over" + g.get(i, i).doubleValue() + "}");
				steps.set(steps.size() - 1, steps.get(steps.size() - 1) + "=" + x.get(0, i));
			}
		}
		if (buildSteps) {
			steps.add("Final \\;\\; solution");
			steps.add("X=" + x.toLatex());
		}
	}

	@Override
	public String nSteps() {
		int n = a.height();
		return ((n * n * n - n) / 3 + (n * n + n) / 2) + " mul & div, " + ((2 * n * n * n - 3 * n * n+ n) / 6 + (n * n - n) / 2) + " sub";
	}

	@Override
	public String toString() {
		return "Gaussian Elimination With Pivoting";
	}

}
